package com.hxs.hxsserver.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hxs.hxsserver.domain.dto.IdDTO;
import com.hxs.hxsserver.domain.dto.ResponseCode;
import com.hxs.hxsserver.domain.dto.device.*;
import com.hxs.hxsserver.domain.entity.device.AlarmRule;
import com.hxs.hxsserver.domain.entity.device.Device;
import com.hxs.hxsserver.domain.entity.device.Factor;
import com.hxs.hxsserver.domain.entity.device.FactorHistory;
import com.hxs.hxsserver.domain.entity.user.User;
import com.hxs.hxsserver.exception.ApiException;
import com.hxs.hxsserver.mapper.device.AlarmRuleMapper;
import com.hxs.hxsserver.mapper.device.DeviceMapper;
import com.hxs.hxsserver.mapper.device.FactorHistoryMapper;
import com.hxs.hxsserver.mapper.device.FactorMapper;
import com.hxs.hxsserver.service.FactorService;
import com.hxs.hxsserver.utils.ByteUtil;
import com.hxs.hxsserver.utils.DozerUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author liuchuan
 * @create 2024/9/27
 */
@Service
@Slf4j
public class FactorServiceImpl extends ServiceImpl<FactorMapper, Factor> implements FactorService {

    @Resource
    private FactorMapper factorMapper;

    @Resource
    private DozerUtil dozerUtil;

    @Resource
    private FactorHistoryMapper factorHistoryMapper;

    @Resource
    private DeviceMapper deviceMapper;
    @Resource
    private AlarmRuleMapper alarmRuleMapper;

    @Override
    public Boolean insertFactor(FactorDTO factorDTO) {
        Factor factor = dozerUtil.map(factorDTO, Factor.class);
        String nodeNo = ByteUtil.decimalToHex(factorDTO.getNodeNo());
//        LambdaQueryWrapper<Factor> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(Factor::getIsDelete,0);
//        queryWrapper.eq(Factor::getNodeNo,nodeNo);
//        List<Factor> factors = factorMapper.selectList(queryWrapper);
//        if("16".equals(factorDTO.getDataType())){
//            //16位的因子可以存在两条数据在数据库
//            if(factors.size()==2){
//                throw new ApiException(ResponseCode.FACTOR_16_ERROR.getCode(), ResponseCode.FACTOR_16_ERROR.getDesc());
//            }else if(factors.size()==1) {
//                factor.setSort(factors.get(0).getSort()+1);
//            }
//        }else {
//            if(factors.size()>=1){
//                throw new ApiException(ResponseCode.FACTOR_32_ERROR.getCode(), ResponseCode.FACTOR_32_ERROR.getDesc());
//            }
//        }
        LambdaQueryWrapper<Factor> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Factor::getIsDelete,0);
        queryWrapper.eq(Factor::getSort,factor.getSort());
        queryWrapper.eq(Factor::getNodeNo,nodeNo);
        queryWrapper.eq(Factor::getDeviceHardwareAddr,factorDTO.getDeviceHardwareAddr());
        List<Factor> factors = factorMapper.selectList(queryWrapper);
        if(factors.size()>0){
            throw new ApiException(ResponseCode.FACTOR_EXISTS_ERROR.getCode(), ResponseCode.FACTOR_EXISTS_ERROR.getDesc());
        }
        this.baseMapper.insert(dozerUtil.map(factorDTO, Factor.class));
        return true;
    }

    @Override
    public Boolean updateFactor(FactorDTO factorDTO) {
        LambdaUpdateWrapper<Factor> updateWrapper = new LambdaUpdateWrapper<>();
        if (factorDTO.getDeviceHardwareAddr() != null) {
            updateWrapper.set(Factor::getDeviceHardwareAddr, factorDTO.getDeviceHardwareAddr());
        }
        if (factorDTO.getDataType() != null) {
            updateWrapper.set(Factor::getDataType, factorDTO.getDataType());
        }
        if (factorDTO.getCoefficient() != null) {
            updateWrapper.set(Factor::getCoefficient, factorDTO.getCoefficient());
        }
        if (factorDTO.getDeviation() != null) {
            updateWrapper.set(Factor::getDeviation, factorDTO.getDeviation());
        }
        if (factorDTO.getDigit() != null) {
            updateWrapper.set(Factor::getDigit, factorDTO.getDigit());
        }
        if (factorDTO.getFactorName() != null) {
            updateWrapper.set(Factor::getFactorName, factorDTO.getFactorName());
        }
        if (factorDTO.getSort() != null) {
            updateWrapper.set(Factor::getSort, factorDTO.getSort());
        }
        if (factorDTO.getUnit() != null) {
            updateWrapper.set(Factor::getUnit, factorDTO.getUnit());
        }
        if (factorDTO.getEnable() != null) {
            updateWrapper.set(Factor::getEnable, factorDTO.getEnable());
        }
        updateWrapper.eq(Factor::getId,factorDTO.getId());
        this.update(updateWrapper);
        return true;
    }

    @Override
    public Boolean deleteFactor(IdDTO factorDTO) {
        LambdaUpdateWrapper<Factor> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Factor::getId, factorDTO.getId());
        updateWrapper.set(Factor::getIsDelete,1);
        baseMapper.update(null,updateWrapper);
        return true;
    }

    @Override
    public FactorDTO getFactorById(IdDTO factorDTO) {
        Factor factor = this.baseMapper.selectById(factorDTO.getId());
        return  dozerUtil.map(factor,FactorDTO.class);
    }

    @Override
    public IPage<FactorDTO> getFactorList(QueryFactorListDTO factorDTO) {
        Page<Device> page = new Page<>(factorDTO.getPage(), factorDTO.getSize());
        IPage<FactorDTO> factorDTOIPage = factorMapper.getDeviceListByUserId(page,factorDTO);
        factorDTOIPage.getRecords().forEach(factorDTO1 ->{
            AlarmRule alarmRule = alarmRuleMapper.selectByFactor(factorDTO1.getId());
            factorDTO1.setAlarmRule(alarmRule);
        });
        return factorDTOIPage;
    }

    @Override
    public List<QueryFactorHisLastList> getFactorHisLastList(String deviceHardwareAddr) {
        List<QueryFactorHisLastList> queryFactorHisLastLists = new ArrayList<>();
        String[] devices = deviceHardwareAddr.split(",");
        for (int i = 0; i < devices.length; i++) {
            QueryFactorHisLastList queryFactorHisLastList = new QueryFactorHisLastList();
            LambdaQueryWrapper<Device> query = new LambdaQueryWrapper<>();
            query.eq(Device::getIsDelete,0);
            query.eq(Device::getDeviceHardwareAddr,devices[i]);
            Device device = deviceMapper.selectOne(query);

            List<QueryFactorHisLast> queryFactorHisLasts = new ArrayList<>();
            LambdaQueryWrapper<Factor> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Factor::getIsDelete,0);
            queryWrapper.eq(Factor::getDeviceHardwareAddr,devices[i]);
            queryWrapper.eq(Factor::getEnable,1);
            List<Factor> factors = factorMapper.selectList(queryWrapper);
            for (Factor factor : factors) {
                LambdaQueryWrapper<FactorHistory> queryWrapper2 = new LambdaQueryWrapper<>();
                queryWrapper2.eq(FactorHistory::getNodeNo, factor.getNodeNo());
                queryWrapper2.eq(FactorHistory::getDeviceHardwareAddr, factor.getDeviceHardwareAddr());
                queryWrapper2.eq(FactorHistory::getSort, factor.getSort());
                queryWrapper2.orderByDesc(FactorHistory::getCreateTime);
                queryWrapper2.last("LIMIT 1");
                //查询对应节点编号和顺序确定因子历史
                FactorHistory factorHistory = factorHistoryMapper.selectOne(queryWrapper2);
                QueryFactorHisLast queryFactorHisLast = new QueryFactorHisLast();
                queryFactorHisLast.setFactorName(factor.getFactorName());
                queryFactorHisLast.setUnit(factor.getUnit());
                queryFactorHisLast.setId(factor.getId());
                queryFactorHisLast.setNodeNo(factor.getNodeNo());
                if (factorHistory != null) {
                    if ("8".equals(factor.getDataType())) {
                        //8位类型的数据只有true 和false
                        if (factorHistory.getValue()==1) {
                            queryFactorHisLast.setValue("正常/打开");
                        }else if(factorHistory.getValue()==0){
                            queryFactorHisLast.setValue("异常/关闭");
                        }
                    }else {
                        //值等于值乘以系数加偏差再保留小数
                        // 计算结果
                        BigDecimal value = BigDecimal.valueOf(factorHistory.getValue());
                        BigDecimal coefficient = new BigDecimal(factor.getCoefficient());
                        BigDecimal deviation = new BigDecimal(factor.getDeviation());
                        BigDecimal result = value.multiply(coefficient)
                                .add(deviation)
                                .setScale(factor.getDigit(), RoundingMode.HALF_UP); // 四舍五入保留小数
                        queryFactorHisLast.setValue(result.toString());
                    }
                }
                queryFactorHisLasts.add(queryFactorHisLast);
            }
            queryFactorHisLastList.setDeviceHardwareAddr(device.getDeviceHardwareAddr());
            queryFactorHisLastList.setDeviceName(device.getDeviceName());
            queryFactorHisLastList.setStatus(device.getDeviceStatus());
            queryFactorHisLastList.setQueryFactorHisLasts(queryFactorHisLasts);
            queryFactorHisLastLists.add(queryFactorHisLastList);
        }

        return queryFactorHisLastLists;
    }

    @Override
    public IPage<ReturnFactorHis> getFactorHisListByNodeno(QueryFactorHisDTO queryFactorHisDTO) {
        Page<ReturnFactorHis> page = new Page<>(queryFactorHisDTO.getPage(), queryFactorHisDTO.getSize());
        return  factorMapper.selectFactorHisByAddr(page,queryFactorHisDTO);
    }
}
